package com.aifast.core.dataScope;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.text.StrBuilder;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.aifast.common.dataScope.DataScope;
import com.aifast.common.util.AiUtil;
import com.aifast.system.sys.entity.SysRole;
import com.aifast.system.sys.entity.UserInfo;
import net.sf.jsqlparser.JSQLParserException;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.LongValue;
import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
import net.sf.jsqlparser.expression.operators.conditional.OrExpression;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import net.sf.jsqlparser.schema.Table;
import net.sf.jsqlparser.statement.select.PlainSelect;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @Author fujian
 * @since 2022/9/6 17:14
 * <p>
 * https://blog.csdn.net/qq_38225558/article/details/122470094?utm_medium=distribute.pc_aggpage_search_result.none-task-blog-2~aggregatepage~first_rank_ecpm_v1~rank_v31_ecpm-1-122470094-null-null.pc_agg_new_rank&utm_term=%E5%B8%B8%E7%94%A8%E7%9A%84%E6%95%B0%E6%8D%AE%E5%AF%B9%E8%B1%A1%E6%9D%83%E9%99%90&spm=1000.2123.3001.4430
 */
public class DataScopeHandler extends AbstractDataScopeHandler {

    public Expression getSqlSegment(PlainSelect select, String mappedStatementId) {
        DataScope dataScope = DataScopeContextHolder.get();
        if (ObjectUtil.isNull(dataScope)) {
            return select.getWhere();
        }
        UserInfo ui = UserInfo.get();
        if (ObjectUtil.isNull(ui)) {
            return select.getWhere();
        }
        // if is admin let it go
        if(UserInfo.isAdmin()){
            return select.getWhere();
        }
        List<SysRole> roles = ui.getRoles();
        if (ObjectUtil.isNull(roles) || roles.size() == 0 || StrUtil.isBlank(roles.get(0).getPermissionType())) {
            /*没有角色将不能看到任何数据*/
            buildEqualsToSql(select, "id", new LongValue(0));
        }else {
            dataScopeFilter(dataScope, ui, select);
        }
        return select.getWhere();
    }


    private static void dataScopeFilter(DataScope dataScope, UserInfo ui, PlainSelect select) {
//        Console.log("拦截到的sql");
//        Console.log();
        StrBuilder sqlString = StrBuilder.create();//替换为hutool里高性能的StrBuilder
        Table table = (Table) select.getFromItem();
        for (SysRole r : ui.getRoles()) {
            Integer type = Convert.toInt(r.getPermissionType());
            if (DataScopeEnum.ALL.type == type) {
                if(isNotNull(sqlString)){
                    sqlString.append(SYSBOL);
                }
            } else if (DataScopeEnum.CUSTOM.type == type) {
                if(isNotNull(sqlString)){
                    sqlString.append(SYSBOL);
                }
                sqlString.append(StrUtil.format(getTableAlias(table) + CUSTOM_SQl, r.getDataScope()));
            } else if (DataScopeEnum.CURRENT_ORG.type == type) {
                if(isNotNull(sqlString)){
                    sqlString.append(SYSBOL);
                }
                sqlString.append(StrUtil.format(getTableAlias(table) + CURRENT_ORG_SQl, ui.getOrgId()));
            } else if (DataScopeEnum.CURRENT_AND_CHILD_ORG.type == type) {
                if(isNotNull(sqlString)){
                    sqlString.append(SYSBOL);
                }
                sqlString.append(StrUtil.format(getTableAlias(table) + CURRENT_AND_CHILD_ORG_SQl, ui.getOrgId(), ui.getOrgId()));
            } else if (DataScopeEnum.ONLY_ME.type == type) {
                if(isNotNull(sqlString)){
                    sqlString.append(SYSBOL);
                }
                sqlString.append(StrUtil.format(getTableAlias(table) + ONLY_ME_SQl, ui.getUserId()));
            }
        }
//        Console.log(sqlString);
        if (StrUtil.isNotBlank(sqlString.toString())) {
            try {
                if(sqlString.toString().contains(SYSBOL)){
                    /*这里的sql 含有多个片段 需要重新拼接*/
                    List<String> strings = Arrays.asList(sqlString.toString().split("\\|\\|"));
                    /*首先去重*/
                    List<String> collect = strings.stream().distinct().collect(Collectors.toList());
                    OrExpression first = new OrExpression();
                    for (String i : collect){
                        if(ObjectUtil.isNull(first.getLeftExpression())){
                            first.setLeftExpression(CCJSqlParserUtil.parseCondExpression(i));
                            continue;
                        }
                        if(ObjectUtil.isNull(first.getRightExpression())){
                            first.setRightExpression(CCJSqlParserUtil.parseCondExpression(i));
                            continue;
                        }
                        OrExpression second = new OrExpression();
                        second.setLeftExpression(first);
                        second.setRightExpression(CCJSqlParserUtil.parseCondExpression(i));
                        first = second;
                    }
                    select.setWhere(new AndExpression(select.getWhere(),first));
                }else {
                    Expression expression = CCJSqlParserUtil.parseCondExpression(sqlString.toString());
                    select.setWhere(new AndExpression(select.getWhere(), expression));
                }

//                Console.log("权限解析后的sql：");
//                Console.log(where);
            } catch (JSQLParserException e) {
                AiUtil.alert("sql解析错误......" + e.getMessage());
            }
        }
        /*释放性能*/
        sqlString.reset();


    }

    private final Map<DataScopeEnum, Function<String,String>> map = new HashMap<>();


}
